package Client;

import Client.gui.BomberManClientGUI;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.util.Scanner;

public class BomberManClient {

    private int port;
    private String username, server;
    private ObjectInputStream sInput;
    private ObjectOutputStream sOutput;
    private Socket socket;
    private BomberManClientGUI cg;
    
    public BomberManClient(String server, int port, String username) {
	        // which calls the common constructor with the GUI set to null
	        this(server, port, username, null);
	    }
    
    public BomberManClient(String server, int port, String username, BomberManClientGUI cg) {
	        this.server = server;
	        this.port = port;
	        this.username = username;
	        // save if we are in GUI mode or not
	        this.cg = cg;
    }

    public static void main(String[] args) {
        
        int portNumber = 7777;
	String serverAddress = "localhost";
        ///***
        //TODO: Geen anonymous username
        //***
	String userName = "Anonymous";

		// depending of the number of arguments provided we fall through
		switch(args.length) {
			// > javac Client username portNumber serverAddr
			case 3:
				serverAddress = args[2];
			// > javac Client username portNumber
			case 2:
				try {
					portNumber = Integer.parseInt(args[1]);
				}
				catch(Exception e) {
					System.out.println("Invalid port number.");
					System.out.println("Usage is: > java Client [username] [portNumber] [serverAddress]");
					return;
				}
			// > javac Client username
			case 1: 
				userName = args[0];
			// > java Client
			case 0:
				break;
			// invalid number of arguments
			default:
				System.out.println("Usage is: > java Client [username] [portNumber] [serverAddress]");
			return;
		}
		// create the Client object
		BomberManClient client = new BomberManClient(serverAddress, portNumber, userName);
		// test if we can start the connection to the Server
		// if it failed nothing we can do
		if(!client.start())
			return;
		
		// wait for messages from user
		Scanner scan = new Scanner(System.in);
		// loop forever for message from the user
		while(true) {
			System.out.print("> ");
			// read message from user
			String msg = scan.nextLine();
			// logout if message is LOGOUT
			if(msg.equalsIgnoreCase("LOGOUT")) {
				client.sendMessage(new ChatMessage(ChatMessage.LOGOUT, ""));
				// break to do the disconnect
				break;
			}
			// message WhoIsIn
			else if(msg.equalsIgnoreCase("WHOISIN")) {
				client.sendMessage(new ChatMessage(ChatMessage.WHOISIN, ""));				
			}
			else {				// default to ordinary message
				client.sendMessage(new ChatMessage(ChatMessage.MESSAGE, msg));
			}
		}
		// done disconnect
		client.disconnect();
    }

    public boolean start() {
		// try to connect to the server
		try {
			socket = new Socket(server, port);
		} 
		// if it failed not much I can so
		catch(Exception ec) {
			display("Error connectiong to server:" + ec);
			return false;
		}
		
		String msg = "Connection accepted " + socket.getInetAddress() + ":" + socket.getPort();
		display(msg);
	
		/* Creating both Data Stream */
		try
		{
			sInput  = new ObjectInputStream(socket.getInputStream());
			sOutput = new ObjectOutputStream(socket.getOutputStream());
		}
		catch (IOException eIO) {
			display("Exception creating new Input/output Streams: " + eIO);
			return false;
		}

		// creates the Thread to listen from the server 
		new ListenFromServer().start();
		// Send our username to the server this is the only message that we
		// will send as a String. All other messages will be ChatMessage objects
		try
		{
			sOutput.writeObject(username);
		}
		catch (IOException eIO) {
			display("Exception doing login : " + eIO);
			disconnect();
			return false;
		}
		// success we inform the caller that it worked
		return true;
	}
    
    public void sendMessage(ChatMessage msg) {
	        try {
	            sOutput.writeObject(msg);
	        }
	        catch(IOException e) {
	            display("Exception writing to server: " + e);
	        }
    }
    
    private void display(String msg) {
	        if(cg == null)
	            System.out.println(msg);      // println in console mode
	        else
	            cg.append(msg + "\n");      // append to the ClientGUI JTextArea (or whatever)
	    }
    
    private void disconnect() {
	        try {
	            if(sInput != null) sInput.close();
	        }
	        catch(Exception e) {} // not much else I can do
	        try {
	            if(sOutput != null) sOutput.close();
	        }
	        catch(Exception e) {} // not much else I can do
	        try{
	            if(socket != null) socket.close();
	        }
	        catch(Exception e) {} // not much else I can do
	         
	        // inform the GUI
	        if(cg != null)
	            cg.connectionFailed();	             
	    }
    
    class ListenFromServer extends Thread {

		public void run() {
			while(true) {
				try {
					String msg = (String) sInput.readObject();
					// if console mode print the message and add back the prompt
					if(cg == null) {
						System.out.println(msg);
						System.out.print("> ");
					}
					else {
						cg.append(msg);
					}
				}
				catch(IOException e) {
					display("Server has close the connection: " + e);
					if(cg != null) 
						cg.connectionFailed();
					break;
				}
				// can't happen with a String object but need the catch anyhow
				catch(ClassNotFoundException e2) {
				}
			}
		}
	}
}